<?php
/**
 * Created by PhpStorm.
 * User: ivi
 * Date: 2019/3/9
 * Time: 10:25
 */

namespace App\Utils;


use App\Repositories\SystemImportLogRepository;
use Box\Spout\Common\Type;
use Box\Spout\Reader\ReaderFactory;
use Box\Spout\Writer\WriterFactory;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;

class Excel
{
    /**'
     * @param $type
     * @param $call
     * @param $colNumber
     * @param int $titleCount
     * @param \Closure $complete
     * @return Output
     * @throws \Box\Spout\Common\Exception\IOException
     * @throws \Box\Spout\Common\Exception\InvalidArgumentException
     * @throws \Box\Spout\Common\Exception\UnsupportedTypeException
     * @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException
     * @throws \Box\Spout\Writer\Exception\WriterNotOpenedException
     */
    public static function import($type, $call, $colNumber, $titleCount = 1, $complete = null)
    {
        set_time_limit(0);
        ini_set('memory_limit', '1512M');
        ini_set('max_execution_time', 0);
        $file = request()->file('file');
        if (!$file) {
            return Output::fail(1, '请选择文件导入的');
        }
        if ($file->getSize() >= 5 * 1024 * 1024) {
            return Output::fail(1, '建议文件大小在5MB内,当前文件大小:' . round($file->getSize() / 1024 / 1024, 2) . 'MB');
        }
        $reportName = $file->getClientOriginalName();
        $successCount = 0;
        $totalNumber = 0;
        $errorNumber = 0;
        $emptyNumber = 0;
        $errorData = [];
        $reader = ReaderFactory::create(Type::XLSX);
        $fileId = uniqid();
        $importPath = $file->storeAs('excel', 'import_' . $fileId . '.xlsx');
        $reader->open(Storage::path($importPath));
        $resultData = [];
        foreach ($reader->getSheetIterator() as $sheet) {
            $key = 0;
            foreach ($sheet->getRowIterator() as $item) {
                $key++;
                if (count($item) < $colNumber) {
                    for ($i = count($item); $i < $colNumber; $i++) {
                        $item[$i] = '';
                    }
                }
                if ($key == 1) {
                    if (count($item) < $colNumber) {
                        return Output::fail(1, '请下载最新的模板进行导入！');
                    }
                    $item[$colNumber] = '错误信息';
                }
                if ($key <= $titleCount) {
                    $errorData[] = $item;
                    continue;
                }
                foreach ($item as $k => $v) {
                    $item[$k] = trim($v);
                }
                if (!count(array_filter($item))) {
                    $item[$colNumber] = '无数据';
                    $errorData[] = $item;
                    $errorNumber++;
                    $emptyNumber++;
                    continue;
                }
                $emptyNumber = 0;
                $totalNumber++;
                try {
                    $call($item, $key, $resultData);
                    $successCount++;
                } catch (ValidationException $e) {
                    $item[$colNumber] = array_first($e->errors())[0];
                    $errorData[] = $item;
                    $errorNumber++;
                } catch (\Exception $e) {
                    $item[$colNumber] = $e->getMessage();
                    Log::info($e->getMessage().'\r\n'.$e->getTraceAsString());
                    $errorData[] = $item;
                    $errorNumber++;
                }
            }
        }
        if ($complete) {
            $complete($successCount, $resultData);
        }
        while ($emptyNumber) {
            array_pop($errorData);
            $emptyNumber--;
            $errorNumber--;
        }
        if ($errorNumber) {
            $error_path = 'excel/error_' . $fileId . '.xlsx';
            $writer = WriterFactory::create(Type::XLSX);
            $writer->openToFile(Storage::path($error_path));
            $writer->addRows($errorData);
            $writer->close();
        } else {
            $error_path = '';
        }
        (new SystemImportLogRepository())->add([
            'type' => $type,
            'total' => $totalNumber,
            'success' => $successCount,
            'error' => $errorNumber,
            'file_name' => $reportName,
            'import_path' => $importPath,
            'error_path' => $error_path
        ]);
        return Output::data($resultData, "<p>导入总条数：$totalNumber</p><p>导入成功条数：$successCount</p><p>导入错误条数：$errorNumber</p>");
    }

    /**
     * @param Builder $query
     * @param string $title
     * @param $call
     * @param string $name
     */
    public static function exportCsv($query, $title, $call, $name = 'csv')
    {
        set_time_limit(0);
        ini_set('memory_limit', '1512M');
        ini_set('max_execution_time', 0);
        ob_start();
        header("Content-Type: application/force-download");
        header("Content-Disposition:filename=" . $name . ".csv");
        $fp = fopen('php://output', 'w');
        fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF)); //转码 防止乱码(比如微信昵称(乱七八糟的))
        foreach ($title as $row) {
            fputcsv($fp, $row);
        }
        $index = 0;
        $query->chunk(10000, function ($data) use (&$index, $call, $fp) {
            foreach ($data as $item) {
                $index++;
                if ($call) {
                    $row = $call($item, $index);
                } else {
                    $row = (array)$item;
                }
                fputcsv($fp, $row);
                unset($item);
                if ($index % 1000 == 0) {
                    ob_flush();
                    flush();
                }
            }
        });
        exit;
    }
}
